/*
 * File     : _ThunkTest.java
 * Created  : 15 May 2011
 *
 * Copyright © 2011 Matthew Wilson (mj. {my-surname} .uk {at} gmail.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "common.h"

JNIEXPORT void JNICALL Java_com_googlecode_dni_internal_thunk_ThunkManager_initThunk(
    JNIEnv* env,
    jclass clazz,
    jclass interfaceType,
    jobject interfaceMethod,
    jobject target,
    jlong thunkDataPointer,
    jboolean sameThread )
{
    size_t* thunkData = (size_t*) JLONG_TO_POINTER( thunkDataPointer );
    
    if ( sameThread == JNI_TRUE )
    {
        JavaVM* javaVM;
        (*env)->GetJavaVM( env, &javaVM );
        thunkData[ 0 ] = (size_t) javaVM;
    }
    else
    {
        thunkData[ 0 ] = (size_t) env;
    }
    
    thunkData[ 1 ] = (size_t) (*env)->NewGlobalRef( env, interfaceType );
    thunkData[ 2 ] = (size_t) (*env)->FromReflectedMethod( env, interfaceMethod );
    thunkData[ 3 ] = (size_t) (*env)->NewGlobalRef( env, target );
}

JNIEXPORT void JNICALL Java_com_googlecode_dni_internal_thunk_ThunkManager_clearThunk(
    JNIEnv* env,
    jclass clazz,
    jlong thunkDataPointer )
{
    size_t* thunkData = (size_t*) JLONG_TO_POINTER( thunkDataPointer );

    jclass interfaceType;
    jobject target;
    
    interfaceType = (jclass) thunkData[ 1 ];
    target = (jclass) thunkData[ 3 ];
    
    if ( interfaceType == NULL || target == NULL )
    {
        (*env)->ThrowNew( env, (*env)->FindClass( env, "java/lang/AssertionError" ), "Uninitialised thunk being cleared" );
    }
    
    if ( interfaceType != NULL )
    {
        (*env)->DeleteGlobalRef( env, interfaceType );
    }
    if ( target != NULL )
    {
        (*env)->DeleteGlobalRef( env, target );
    }
    
    thunkData[ 0 ] = 0;
    thunkData[ 1 ] = 0;
    thunkData[ 2 ] = 0;
    thunkData[ 3 ] = 0;
}
